<template>
  <div class="scene-camera" ref="scene"></div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import * as THREE from 'three'
import { getIntersects } from '@/utils/helper'
import { provinceList } from '@/config/index'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

let mixer: THREE.AnimationMixer
const clock = new THREE.Clock()
let provinceState: THREE.Object3D<THREE.Event> | undefined

const playEarthAnimation = (model: any, animations: any) => {
  let duration = 0
  mixer = new THREE.AnimationMixer(model)

  if (!animations && !animations.lenght) return
  for (const animation of animations) {
    // 返回动画操作对象
    const action = mixer.clipAction(animation)
    // 剪辑对象设置播放结束时间
    duration = duration + animation.duration
    // 暂停在最后一帧播放的状态
    action.clampWhenFinished = true
    // 只播放一次
    action.setLoop(THREE.LoopOnce, 1).play()
  }

  mixer.addEventListener('finished', () => {
    console.log('--- finished ---')
    // onChange(eventType, model, fn, showOfficeName)
  })
}

const provinceHighlight = (object: any) => {
  if (provinceState === undefined) return
  const target = object.name.split('-')[0]
  provinceState.traverse((child: any) => {
    if (child.material) {
      if (child.name.includes(target)) {
        const t = 1.05
        // const t = 1.008
        child.scale.x = t
        child.scale.y = t
        child.scale.z = t
      } else {
        const t = 1
        child.scale.x = t
        child.scale.y = t
        child.scale.z = t
      }
    }
  })
}

let camera: THREE.PerspectiveCamera
// 创建渲染器
const render = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true
})
// render.setClearColor(0xffffff, 0)
render.setPixelRatio(window.devicePixelRatio)

// 创建场景
const scene = new THREE.Scene()
scene.background = new THREE.Color(0xeaeaea)

export default defineComponent({
  name: 'SceneCamera',
  mounted () {
    this.createCamera()
    this.loadImgSrc()
    render.domElement.addEventListener('mousemove', (event) => {
      console.log('first provinceHighlight')
      const intersects = getIntersects(event, scene, camera, render.domElement)
      for (const v of intersects) {
        if (v.object.name.includes('省面')) provinceHighlight(v.object)
      }
    })
  },
  methods: {
    sceneRef () {
      return this.$refs.scene as HTMLElement
    },
    createCamera () {
      const el = this.sceneRef()
      const { clientHeight, clientWidth } = el
      camera = new THREE.PerspectiveCamera(36, clientWidth / clientHeight, 0.1, 10000)
      camera.position.set(1, 1, 3.6)
      el.appendChild(render.domElement)
      this.initOrbitControls()
      render.setSize(clientWidth, clientHeight)
    },
    loadImgSrc () {
      // 坐标轴辅助
      scene.add(new THREE.AxesHelper(100))
      // 添加灯光
      scene.add(new THREE.AmbientLight(0xffffff, 0.8))
      function animate () {
        requestAnimationFrame(animate)
        render.render(scene, camera)
        mixer && mixer.update(clock.getDelta())
      }

      const loader = new GLTFLoader()
      loader.load('./textures/a4.gltf?v2', (gltf) => {
        // console.log(gltf)
        const earth = gltf.scene

        const animations = gltf.animations
        provinceState = earth.getObjectByName('省份')

        gltf.scene.traverse((v: any) => {
          // if (v.material && ['四川-省面-75'].includes(v.name)) {
          //   v.material.roughness = 0.3
          //   v.material.emissiveIntensity = 30
          //   v.material.color.set(0xff0000)
          //   console.log(v.material)
          // }

          if (v.material === undefined) return
          if (v.name === '中国-中国材质') {
            v.material.emissiveIntensity = 5
          }
          if (v.name === '中国-中国边界') {
            v.material.emissiveIntensity = 100
          }
          if (v.name === '中国-中国厚度') {
            v.material.emissiveIntensity = 0.5
          }
          if (v.name === '地球1') {
            v.material.emissiveIntensity = 30
            v.material.roughness = 0.3
          }
        })
        earth && scene.add(earth)

        this.changeBgColor(earth)

        setTimeout(() => {
          playEarthAnimation(earth, animations)
        }, 1000)

        animate()
      })
    },
    initOrbitControls () {
      const controls = new OrbitControls(camera, render.domElement)
      controls.enableZoom = true
      controls.autoRotate = false
      controls.enablePan = true
      controls.enableDamping = true
      controls.autoRotateSpeed = 2
    },
    changeBgColor (earth: THREE.Group) {
      let i = 1
      const t = 1.008
      earth.traverse((child: any) => {
        if (!child.material) return

        const prev = child.name.split('-')[0]
        provinceList.forEach((item) => {
          if (prev === item.name) {
            i = 10 * item.heat

            // 层级不一样，导致缩放比例不一样
            if (['日本', '韩国'].includes(item.name)) {
              child.parent.scale.x = 1.014
              child.parent.scale.y = 1.014
              child.parent.scale.z = 1.014
            } else {
              child.parent.scale.x = t
              child.parent.scale.y = t
              child.parent.scale.z = t
            }

            child.material.opacity = 1
            child.material.emissiveIntensity = i
          }
        })
      })
    }
  }
})
</script>

<style scoped lang="scss">
.scene-camera {
  margin-top: 20px;
  display: inline-block;
  // display: flex;
  width: 960px;
  height: 640px;
  cursor: pointer;
}
</style>
